package io.renren.modules.generator.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.renren.common.utils.DateUtils;
import io.renren.constant.DeviceFinal;
import io.renren.modules.generator.dao.DeviceWarningQuotaDao;
import io.renren.modules.generator.dao.StatsDao;
import io.renren.modules.generator.entity.DeviceAllEntity;
import io.renren.modules.generator.entity.DeviceSiteEntity;
import io.renren.modules.generator.enums.EquipmentNumberComparisonEnum;
import io.renren.modules.generator.service.DeviceSiteService;
import io.renren.modules.generator.service.IntellisenseStatsService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @ClassName IntellisenseStatsServiceImpl
 * @Description TODO
 * @Author zhengd
 * @Date 2020/9/11 20:55
 * @Version 1.0
 **/
@Service
public class IntellisenseStatsServiceImpl implements IntellisenseStatsService {

    @Autowired
    private DeviceSiteService deviceSiteService;

    @Autowired
    private StatsDao statsDao;

    @Autowired
    private DeviceWarningQuotaDao deviceWarningQuotaDao;

    @Override
    public Object quota(String time, String type, String code) {
        double value = 0;
        if (StringUtils.equals(time, "hour")) {
            if (StringUtils.equals(DeviceFinal.water_type, type)) {
                if (StringUtils.equals(DeviceFinal.WATER_Quota_w21003_Rtd, code)) {
                    return DeviceFinal.HOUR_WATER_Quota_w21003_Rtd.doubleValue();
                } else if (StringUtils.equals(DeviceFinal.WATER_Quota_w21011_Rtd, code)) {
                    return DeviceFinal.HOUR_WATER_Quota_w21011_Rtd.doubleValue();
                } else if (StringUtils.equals(DeviceFinal.WATER_Quota_w01001_Rtd, code)) {
                    return DeviceFinal.HOUR_WATER_Quota_w01001_Rtd_less.doubleValue() + "-" + DeviceFinal.HOUR_WATER_Quota_w01001_Rtd_more.doubleValue();
                }
            } else if (StringUtils.equals(DeviceFinal.smoke_type, type)) {
                if (StringUtils.equals(DeviceFinal.SMOKE_01_Rtd, code)) {
                    return DeviceFinal.HOUR_SMOKE_01_Rtd.doubleValue();
                } else if (StringUtils.equals(DeviceFinal.SMOKE_02_Rtd, code)) {
                    return DeviceFinal.HOUR_SMOKE_02_Rtd.doubleValue();
                } else if (StringUtils.equals(DeviceFinal.SMOKE_03_Rtd, code)) {
                    return DeviceFinal.HOUR_SMOKE_03_Rtd.doubleValue();
                }
            } else if (StringUtils.equals(DeviceFinal.vocs_type, type)) {
                if (StringUtils.equals(DeviceFinal.GAS_Quota_a24088_Rtd, code)) {
                    return DeviceFinal.HOUR_GAS_Quota_a24088_Rtd.doubleValue();
                } else if (StringUtils.equals(DeviceFinal.GAS_Quota_a05002_Rtd, code)) {
                    return DeviceFinal.HOUR_GAS_Quota_a05002_Rtd.doubleValue();
                } else if (StringUtils.equals(DeviceFinal.GAS_Quota_a24087_Rtd, code)) {
                    return DeviceFinal.HOUR_GAS_Quota_a24087_Rtd.doubleValue();
                }
            } else if (StringUtils.equals(DeviceFinal.sweage_type, type)) {
                if (StringUtils.equals(DeviceFinal.SWEAGE_Ch1, code)) {
                    return DeviceFinal.ACTUAL_SWEAGE_Ch1.doubleValue();
                }
            }
        }
        return value;
    }

    @Override
    public Object statsAvg(String dateStr, String type, Map<String, String> codeMap) {
        return statsAvg(dateStr, type, codeMap, null, null);
    }

    @Override
    public Object statsAvg(String dateStr, String site, String code) {
        return statsAvg(dateStr, null, null, site, code);
    }

    @Override
    public Object statDetail(String dateStr, String type, Map<String, String> codeMap) {
        return statDetail(dateStr, type, codeMap, null, null,false);
    }


    @Override
    public Object statDetail(String dateStr, String site, String code) {
        return statDetail(dateStr, null, null, site, code,true);
    }

    @Override
    public Object statWeekDetail(String dateStr, String site, String code) {
        List<DeviceAllEntity> deviceAllEntities;
        JSONObject chartObject = new JSONObject(true);
        //获取时间列表
        LocalDateTime localDateTime = getLocalDateTime(dateStr);
        String endDay = localDateTime.toLocalDate().format(DateTimeFormatter.ofPattern(DateUtils.DATE_PATTERN));
        String startDay = localDateTime.toLocalDate().minusDays(7).format(DateTimeFormatter.ofPattern(DateUtils.DATE_PATTERN));
        //查询每小时列表数据
        deviceAllEntities = getStatsDao().statsWeekDetail(site,code,startDay,endDay);
        JSONObject codeObject = new JSONObject(true);
        List<Integer> warningDays = getDeviceWarningQuotaDao().selectDays(startDay,endDay,site,code);
        Object[] hourArr = fillArr(deviceAllEntities,site,code,false,Arrays.asList(0,1,2,3,4,5,6),true,warningDays,null);
        codeObject.put(StringUtils.isBlank(code)?"common":code, Arrays.asList(hourArr));
        chartObject.put(site, codeObject);
        return chartObject;
    }

    private Object statsAvg(String dateStr, String type, Map<String, String> codeMap,String site,String code) {
        List<DeviceAllEntity> deviceAllEntities;
        JSONObject chartObject = new JSONObject(true);
        //获取时间列表
        LocalDateTime localDateTime = getLocalDateTime(dateStr);
        String queryDate = localDateTime.toLocalDate().format(DateTimeFormatter.ofPattern(DateUtils.DATE_PATTERN));
        int year = localDateTime.getYear();
        if (StringUtils.isBlank(type) && CollectionUtils.isEmpty(codeMap)
                && StringUtils.isNotBlank(site)) {
            JSONObject codeObject = new JSONObject(true);
            deviceAllEntities = getStatsDao().statsAvg(queryDate, year,site,code, null);
            Object[] avgArr = fillArr(deviceAllEntities,site,code,true,null,false,null,null);
            codeObject.put(StringUtils.isBlank(code)?"common":code, Arrays.asList(avgArr));
            chartObject.put(site, codeObject);
        } else if (StringUtils.isNotBlank(type) && !CollectionUtils.isEmpty(codeMap) ) {
            //查询监测点位列表
            QueryWrapper queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("device_type", type);
            List<DeviceSiteEntity> siteList = getDeviceSiteService().list(queryWrapper);
            deviceAllEntities = getStatsDao().statsAvg(queryDate, year,null,null, siteList);
            for (DeviceSiteEntity deviceSiteEntity:siteList) {
                JSONObject codeObject = new JSONObject(true);
                Iterator<Map.Entry<String,String>> iterator = codeMap.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String,String> codeEntry = iterator.next();
                    Object[] avgArr = fillArr(deviceAllEntities,deviceSiteEntity.getDeviceCode(),codeEntry.getKey(),true,null,false,null,null);
                    codeObject.put(codeEntry.getKey(), Arrays.asList(avgArr));
                }
                chartObject.put(deviceSiteEntity.getDeviceCode(), codeObject);
            }
        }
        return chartObject;
    }

    private Object statDetail(String dateStr, String type, Map<String,String> codeMap,String site,String code,boolean warning) {
        String tableName;
        List<DeviceAllEntity> deviceAllEntities;
        List<Integer> warningHours = null;
        JSONObject chartObject = new JSONObject(true);
        //获取时间列表
        LocalDateTime localDateTime = getLocalDateTime(dateStr);
        String queryTime = localDateTime.toLocalDate().format(DateTimeFormatter.ofPattern(DateUtils.DATE_PATTERN));
        List<Integer> hours = Stream.iterate(0, i -> i + 1).limit(localDateTime.getHour() + 1).collect(Collectors.toList());
        if (StringUtils.isBlank(type) && CollectionUtils.isEmpty(codeMap)
                && StringUtils.isNotBlank(site)) {
            JSONObject codeObject = new JSONObject(true);
            //特殊处理多普勒数据
            if (StringUtils.equals(site, DeviceFinal.doppler_encrypt_01)) {
                deviceAllEntities = getStatsDao().statsDetail(queryTime,site,code, "device_all_11");
                if (warning) {
                    warningHours = getDeviceWarningQuotaDao().selectHours(queryTime,site,code,"actual_warning");
                }
            } else if (StringUtils.equals(site, DeviceFinal.doppler_encrypt_02)){
                deviceAllEntities = getStatsDao().statsDetail(queryTime,site,code, "device_all_12");
                if (warning) {
                    warningHours = getDeviceWarningQuotaDao().selectHours(queryTime,site,code,"actual_warning");
                }
            } else {
                //查询每小时列表数据
                tableName = getTableName(site);
                deviceAllEntities = getStatsDao().statsDetail(queryTime,site,code, tableName);
                if (warning) {
                    warningHours = getDeviceWarningQuotaDao().selectHours(queryTime,site,code,"hour_warning");
                }
            }
            Object[] hourArr = fillArr(deviceAllEntities,site,code,false,hours,warning,warningHours,queryTime);
            codeObject.put(StringUtils.isBlank(code)?"common":code, Arrays.asList(hourArr));
            chartObject.put(site, codeObject);
        } else if (StringUtils.isNotBlank(type) && !CollectionUtils.isEmpty(codeMap) ) {
            QueryWrapper queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("device_type", type);
            List<DeviceSiteEntity> siteList = getDeviceSiteService().list(queryWrapper);
            //开始封装统计图数据
            for (DeviceSiteEntity deviceSite:siteList) {
                JSONObject codeObject = new JSONObject(true);

                //特殊处理多普勒数据
                if (StringUtils.equals(deviceSite.getDeviceCode(), DeviceFinal.doppler_encrypt_01)) {
                    deviceAllEntities = getStatsDao().statsDetail(queryTime,deviceSite.getDeviceCode(),null, "device_all_11");
                } else if (StringUtils.equals(deviceSite.getDeviceCode(), DeviceFinal.doppler_encrypt_02)){
                    deviceAllEntities = getStatsDao().statsDetail(queryTime,deviceSite.getDeviceCode(),null, "device_all_12");
                } else {
                    //查询每小时列表数据
                    tableName = getTableName(deviceSite.getDeviceCode());
                    deviceAllEntities = getStatsDao().statsDetail(queryTime,deviceSite.getDeviceCode(),null, tableName);
                }
                Iterator<Map.Entry<String,String>> iterator = codeMap.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String,String> codeEntry = iterator.next();
                    Object[] hourArr = fillArr(deviceAllEntities,deviceSite.getDeviceCode(),codeEntry.getKey(),false,hours,false,null,null);
                    codeObject.put(codeEntry.getKey(), Arrays.asList(hourArr));
                }
                chartObject.put(deviceSite.getDeviceCode(), codeObject);
            }
        }
        return chartObject;
    }

    /**
     * @param dateStr 日期
     * @return
     */
    private LocalDateTime getLocalDateTime (String dateStr) {
        //获取时间列表
        LocalDateTime localDateTime = LocalDateTime.parse(dateStr,
                DateTimeFormatter.ofPattern(DateUtils.DATE_TIME_PATTERN));
        return localDateTime;
    }

    /**
     * 通过设备编号获取需要查询的表名
     * @param deviceCode 设备编号
     * @return
     */
    private String getTableName (String deviceCode) {
        return "device_hour_" + EquipmentNumberComparisonEnum.valueOf(deviceCode).getCode();
    }

    /**
     * 简单重复代码抽离
     * @param deviceAllEntities
     * @param site
     * @param code
     * @param hours
     */
    private Object[] fillArr (List<DeviceAllEntity> deviceAllEntities,String site,String code,boolean ifAvg,List<Integer> hours,boolean warning,List<Integer> warningHours,String queryTime) {
        final Object[] arr;
        if (ifAvg) {
            arr = new String[2];
            Arrays.fill(arr, "0");
        } else if (warning) {
            arr = new Object[hours.size()];
            String[] arrInner = {"0","0","0"};
            Arrays.fill(arr, arrInner);
        } else {
            arr = new String[hours.size()];
            Arrays.fill(arr, "0");
        }
        if (!CollectionUtils.isEmpty(deviceAllEntities)) {
            deviceAllEntities.stream().forEach(deviceEntity -> {
                if (StringUtils.equals(deviceEntity.getDeviceEncrypt(), site)
                        && StringUtils.equals(deviceEntity.getDeviceCode(), code)) {
                    if (CollectionUtils.isEmpty(hours)) {
                        if (StringUtils.isNotBlank(deviceEntity.getDayAvg())) {
                            arr[0] = deviceEntity.getDayAvg();
                        }
                        if (StringUtils.isNotBlank(deviceEntity.getYearAvg())) {
                            arr[1] = deviceEntity.getYearAvg();
                        }
                    } else if (warning) {
                        String[] arrObj = {"0",deviceEntity.getHour() + "","0"};
                        arr[deviceEntity.getHour()] = arrObj;
                        if (hours.contains(deviceEntity.getHour())) {
                            arrObj = new String[]{deviceEntity.getDeviceValue(), deviceEntity.getHour() + "",warningHours.stream().filter(p -> p == deviceEntity.getHour()).count() == 1?deviceEntity.getDeviceValue():"0"};
                            arr[deviceEntity.getHour()] = arrObj;
                        }
                    } else {
                        if (hours.contains(deviceEntity.getHour())) {
                            arr[deviceEntity.getHour()] = deviceEntity.getDeviceValue();
                        }
                    }
                }
            });
        }
        return arr;
    }

    public DeviceSiteService getDeviceSiteService() {
        return deviceSiteService;
    }

    public StatsDao getStatsDao() {
        return statsDao;
    }

    public DeviceWarningQuotaDao getDeviceWarningQuotaDao() {
        return deviceWarningQuotaDao;
    }
}
